import Cookies from 'js-cookie';
import { AESUtils } from '@/utils'

/**
 * window.localStorage 浏览器永久缓存
 * @method set 设置永久缓存
 * @method get 获取永久缓存
 * @method remove 移除永久缓存
 * @method clear 移除全部永久缓存
 */
export const Local = {
  // 查看 v2.4.3版本更新日志
  setKey(key) {
    // @ts-ignore
    return `${__NEXT_NAME__}:${key}`;
  },
  // 设置永久缓存
  set(key, val) {
    window.localStorage.setItem(Local.setKey(key), JSON.stringify(val));
  },
  // 获取永久缓存
  get(key) {
    let json = window.localStorage.getItem(Local.setKey(key));
    return JSON.parse(json);
  },
  // 移除永久缓存
  remove(key) {
    window.localStorage.removeItem(Local.setKey(key));
  },
  // 移除全部永久缓存
  clear() {
    window.localStorage.clear();
  },
};

/**
 * window.sessionStorage 浏览器临时缓存
 * @method set 设置临时缓存
 * @method get 获取临时缓存
 * @method remove 移除临时缓存
 * @method clear 移除全部临时缓存
 */
export const Session = {
  // 设置临时缓存
  set(key, val) {
    if (key === 'token') return Cookies.set(key, val);
    window.sessionStorage.setItem(Local.setKey(key), JSON.stringify(val));
  },
  // 获取临时缓存
  get(key) {
    if (key === 'token') return Cookies.get(key);
    let json = window.sessionStorage.getItem(Local.setKey(key));
    return JSON.parse(json);
  },
  // 移除临时缓存
  remove(key) {
    if (key === 'token') return Cookies.remove(key);
    window.sessionStorage.removeItem(Local.setKey(key));
  },
  // 移除全部临时缓存
  clear() {
    Cookies.remove('token');
    Cookies.remove('username');
    window.sessionStorage.clear();
  },
};

/**
 * 自定义的本地缓存类
 */
export class Storage {
  /**
   * 构造函数
   * @param {String} symbol 缓存标识
   */
  constructor(config) {
    const def = {
      type: 'Local',
      symbol: __NEXT_NAME__,
      encrypt: false,
    }
    // 缓存类型
    this.type = config ? config.type || def.type : def.type
    // 默认缓存名称前缀
    this.symbol = config ? config.symbol || def.symbol : def.symbol
    // 是否开启加密
    this.encrypt = config ? config.encrypt || def.encrypt : def.encrypt
    // 默认到期时间，单位: s (秒)，默认14天
    this.expires = 60 * 60 * 24 * 14
  }
  /**
   * 组装缓存的关键字
   *
   * @param {String} key 缓存的关键字
   * @returns {String} 组装后的关键字
   */
  getKey(key) {
    return `${this.symbol}:${key}`
  }
  /**
   * 设置本地缓存数据
   * 
   * @param {String} key 缓存的关键字
   * @param {Any} value 缓存的内容
   * @param {Number} expires 过期时间，单位：s(秒)
   */
  set(key, value, expires) {
    // 设置过期时间
    if (expires && typeof expires !== 'number') {
      console.warn('Storage.set()方法中，expires变量需要为数字类型，且不可为0！')
      return
    }
    let result = { value }
    if (expires) {
      result['expires'] = +new Date() + expires * 1000
    }
    // let finalData = JSON.stringify(result)
    // 开启了加密
    if (this.encrypt) {
      result = AESUtils.encrypt(result, key)
    } else {
      result = JSON.stringify(result)
    }
    if (this.type === 'Local') {
      localStorage.setItem(this.getKey(key), result)
    } else {
      sessionStorage.setItem(this.getKey(key), result)
    }
  }
  /**
   * 获取指定的缓存信息
   *
   * @param {String} key 缓存的关键字
   * @returns 
   */
  get(key) {
    let result = {}
    if (this.type === 'Local') {
      result = localStorage.getItem(this.getKey(key))
    } else {
      result = sessionStorage.getItem(this.getKey(key))
    }
    // 缓存不存在
    if (!result) {
      // console.warn(`关键字为[${key}]的缓存不存在！`)
      return null
    }

    try {
      if (this.encrypt) {
        result = AESUtils.decrypt(result, key)
      } else {
        result = JSON.parse(result)
      }
      // 缓存过期
      if (result.expires && +new Date() > result.expires) {
        // console.warn(`关键字为[${key}]的缓存已过期！`)
        this.remove(key)
        return null
      }
      if (result.hasOwnProperty('value')) {
        return result?.value || ''
      } else {
        return result
      }
    } catch (err) {
      console.warn('[ControlStorage] the error message: get field failed\n', err);
    }
  }
  /**
   * 删除指定的缓存信息
   *
   * @param {String} key 缓存的关键字
   */
  remove(key) {
    if (this.type === 'Local') {
      localStorage.removeItem(this.getKey(key))
    } else {
      sessionStorage.removeItem(this.getKey(key))
    }
  }
  /**
   * 清理过期缓存
   */
  clearExpire() {
    // 清除 localStorage 超时缓存
    for (const key of Object.keys(localStorage)) {
      try {
        let storageItem = localStorage[key]
        if (this.encrypt) {
          storageItem = AESUtils.decrypt(storageItem)
        }
        if (!this.isValidJson(storageItem)) {
          continue;
        }
        storageItem = JSON.parse(storageItem)
        if (storageItem && !storageItem.hasOwnProperty('expires')) {
          continue;
        }
        if (typeof storageItem.expires !== 'number') {
          continue;
        }
        if (+new Date() > storageItem.expires) {
          localStorage.removeItem(key)
        }
      } catch (err) {
        console.error(`Storages key [${key}] value is null`, err)
        continue;
      }
    }
    // 清除 sessionStorage 超时缓存
    for (const key of Object.keys(sessionStorage)) {
      try {
        let storageItem = sessionStorage[key]
        if (this.encrypt) {
          storageItem = AESUtils.decrypt(storageItem)
        }
        if (!this.isValidJson(storageItem)) {
          continue;
        }
        storageItem = JSON.parse(storageItem)
        if (storageItem && !storageItem.hasOwnProperty('expires')) {
          continue;
        }
        if (typeof storageItem.expires !== 'number') {
          continue;
        }
        if (+new Date() > storageItem.expires) {
          sessionStorage.removeItem(key)
        }
      } catch (err) {
        console.error(`Storages key [${key}] value is null`, err)
        continue;
      }
    }
  }
  /**
   * 校验是否可以进行json转义
   *
   * @param {Any} value 内容
   * @returns 
   */
  isValidJson(value) {
    try {
      if (value && value.startsWith('{')) {
        JSON.parse(value)
        return true;
      } else {
        return false;
      }
    } catch (error) {
      if (error instanceof SyntaxError) {
        return false;
      } else {
        throw error;
      }
    }
  }
}
export const ScoreTimeStorage = new Storage({ type: 'Local', symbol: 'scoreTime' })
export const ScoreWriteStorage = new Storage({ type: 'Local', symbol: 'scorewrite' })
export const ScoreStorage = new Storage({ type: 'Local', symbol: 'score' })
export const LocalStorage = new Storage({ type: 'Local' })
export const SessionStorage = new Storage({ type: 'Session', encrypt: true })
